#pragma once 

#include <iostream>
#include <string>
#include <sys/types.h>
#include <sys/socket.h>
#include <cstring>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/wait.h>

#define DEFAULT 8080

class UdpServer{
  private:
    int port;
    int sockfd;
    //std::string ip; // = "127.0.0.1"; //后面去掉

  public:
    //UdpServer(std::string _ip, int _port = DEFAULT)
    UdpServer(int _port = DEFAULT)
      :port(_port)
      ,sockfd(-1)
      //,ip(_ip)
    {}

    bool InitUdpServer() // 初始化服务器
    {
      //1. socket函数
      sockfd = socket(AF_INET, SOCK_DGRAM, 0);
      if(sockfd < 0)
      {
        std::cerr << " socket error" << std::endl;
        return false;
      }

      std::cout << "socket create success , sockfd；"<< sockfd << std::endl;

      //2. 绑定 网络属性信息
      struct sockaddr_in local;
      memset(&local, '\0', sizeof(local));
      local.sin_family = AF_INET;
      local.sin_port = htons(port);//port需要发送到网络中，需要转为网络序列
      //local.sin_addr.s_addr = inet_addr(ip.c_str());  //inet_addr 是C语言接口字符串转整数
      local.sin_addr.s_addr = INADDR_ANY;
      
      if(bind(sockfd, (struct sockaddr*)&local, sizeof(local)) < 0)//绑定
      {
        std::cerr << "bind error" << std::endl;
        return false;
      }
      std::cout << "bind success" << std::endl;

      return true;
    }

    void Start() //循环运行
    {
      char buffer[128] = {0};
      //dup2(sockfd, 1);

      for( ; ; )
      {
        //udp 需要读取数据、对端信息
        struct sockaddr_in peer; //远端
        socklen_t len = sizeof(peer);

        ssize_t size = recvfrom(sockfd, buffer, sizeof(buffer)-1, 0, (struct sockaddr*)&peer, &len);
        if(size > 0)
        {
          buffer[size] = 0;
          int _port = ntohs(peer.sin_port);//网络序列转主机序列
          std::string _ip = inet_ntoa(peer.sin_addr);// 
          std::cout << _ip << " : " << _port << " # " << buffer << std::endl;
          
          // 执行程序
          std::string cmd = buffer;
          std::string result;
          if(cmd == "ls")
          {
            int pipes[2];
            pipe(pipes);

            pid_t id = fork();
            if(id == 0)
            {
              //child 
              close(pipes[0]);
              dup2(pipes[1], 1);
              execl("usr/bin/ls", "ls", "-a", "-l", "-i", nullptr);
              exit(1);
            }
            close(pipes[1]);
            char c;
            while(1)
            {
              if(read(pipes[0], &c, 1) > 0)
              {
                result.push_back(c);
              }
              else 
              {
                break;
              }
            }
            wait(nullptr);
          }

          std::string echo_msg;
          if(result.empty())
          {
             //std::string echo_msg = "server get!-> ";
             echo_msg += buffer;
             echo_msg = "server get!->";
          }
          else 
          {
            echo_msg = result;
          }
          sendto(sockfd, echo_msg.c_str(), echo_msg.size(), 0, (struct sockaddr*)&peer, len);

        }
        else 
        {
          std::cerr << "recvfrom error" << std::endl; 
        }

      }//end for 


    }

    ~UdpServer()
    {
      if(sockfd > 0) close(sockfd);
    }
};
